#![cfg_attr(feature = "axstd", no_std)]
#![cfg_attr(feature = "axstd", no_main)]

extern crate axplat_aarch64_phytium_pi;

use axhal::ddma::Ddma;
use axhal::fiomux::{fiomux_init, fiopad_set_i2s_mux_pd2308};
use axhal::i2s::I2s;

use axhal::mem::pa;
use axhal::mem::{PhysAddr, phys_to_virt};

use axhal::time;

#[cfg(feature = "axstd")]
use axstd::println;

#[cfg_attr(feature = "axstd", unsafe(no_mangle))]
fn main() {
    println!("println: this is i2s_play_from_record demo.");
    // Board: PD2308 defaults
    const DDMA5_BASE: PhysAddr = pa!(0x2800_1000);
    const I2S3_BASE: PhysAddr = pa!(0x2800_5000);

    // init iomux and set i2s mux
    fiomux_init();
    fiopad_set_i2s_mux_pd2308();

    // map device bases
    let ddma_base = phys_to_virt(DDMA5_BASE).as_mut_ptr();
    let i2s_base = phys_to_virt(I2S3_BASE).as_mut_ptr();
    let ddma = Ddma::new(ddma_base);
    let i2s = I2s::new(i2s_base);

    // configure i2s
    i2s.reset_fifos();
    i2s.set_clk_div(44_100);
    // device-side dma register offsets for i2s
    i2s.set_dma_addrs(0x01C0, 0x01C8);
    i2s.enable_tx_rx();

    // simple ping-pong buffers in DDR (addresses are examples; replace with real buffers if needed)
    static mut RX_BUF: [u32; 16384] = [0; 16384];
    static mut TX_BUF: [u32; 16384] = [0; 16384];
    let total_bytes = (core::mem::size_of::<u32>() * 16384) as u32;

    // configure ddma channels: rx ch1, tx ch0
    ddma.reset();
    ddma.enable();
    unsafe {
        let rx_ddr = (&raw const RX_BUF as *const u32 as usize) as u64;
        let tx_ddr = (&raw const TX_BUF as *const u32 as usize) as u64;
        // RX from device to DDR (rx_mode = true)
        ddma.configure_chan_basic(
            1,
            (I2S3_BASE.as_usize() + 0x01C0) as u32,
            rx_ddr,
            total_bytes,
            true,
        );
        // TX from DDR to device (rx_mode = false)
        ddma.configure_chan_basic(
            0,
            (I2S3_BASE.as_usize() + 0x01C8) as u32,
            tx_ddr,
            total_bytes,
            false,
        );
    }

    println!("I2S RX/TX started with DDMA (basic mode). ");

    loop {
        time::busy_wait(time::Duration::from_secs(1));
        println!("tick");
    }
}
